{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true,
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "第三节：附加项目:多线程基础\n",
    "=="
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "多线程类似于同时执行多个不同程序，多线程运行有如下优点：\n",
    "\n",
    "<font face=\"黑体\" color=blue size=4>\n",
    "1.使用线程可以把占据长时间的程序中的任务放到后台去处理。\n",
    "\n",
    "2.用户界面可以更加吸引人，比如用户点击了一个按钮去触发某些事件的处理，可以弹出一个进度条来显示处理的进度。\n",
    "\n",
    "3.程序的运行速度可能加快。\n",
    "\n",
    "4.在一些等待的任务实现上如用户输入、文件读写和网络收发数据等，线程就比较有用了。在这种情况下我们可以释放一些珍贵的资源如内存占用等等。\n",
    "</font>\n",
    "\n",
    "每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行，必须依存在应用程序中，由应用程序提供多个线程执行控制。\n",
    "\n",
    "每个线程都有他自己的一组CPU寄存器，称为线程的上下文，该上下文反映了线程上次运行该线程的CPU寄存器的状态。\n",
    "\n",
    "**Python中使用线程有两种方式：函数或者用类来包装线程对象。**\n",
    "\n",
    "在Python中有多个模块可以创建进程，比较常用的有os.fork()函数、multiprocessing模块和Pool进程池。由于os.fork()函数只适用于Unix/Linux/Mac系统上运行，在Windows操作系统中不可用，所以本章重点介绍multiprocessing模块和Pool进程池这2个跨平台模块。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thread start......\n",
      "Thread-0\n",
      "Thread start......\n",
      "Thread-1\n",
      "Thread start......Thread start......\n",
      "Thread-3\n",
      "\n",
      "Thread-2\n",
      "Thread start......\n",
      "Thread-4\n",
      "Thread start......\n",
      "Thread-5\n",
      "Thread start......\n",
      "Thread-6\n",
      "Thread start......\n",
      "Thread start......\n",
      "Thread-8\n",
      "Thread-7Thread start......\n",
      "Thread-9\n",
      "\n",
      "Thread-16: Tue Jul  7 17:32:32 2020\n",
      "Quit thread......\n",
      "Thread-17: Tue Jul  7 17:32:32 2020\n",
      "Thread-18: Tue Jul  7 17:32:32 2020Thread-19: Tue Jul  7 17:32:32 2020\n",
      "\n",
      "Thread-20: Tue Jul  7 17:32:32 2020\n",
      "Thread-21: Tue Jul  7 17:32:32 2020\n",
      "Thread-22: Tue Jul  7 17:32:32 2020\n",
      "Thread-24: Tue Jul  7 17:32:32 2020\n",
      "Thread-25: Tue Jul  7 17:32:32 2020Thread-23: Tue Jul  7 17:32:32 2020\n",
      "\n",
      "Thread-17: Tue Jul  7 17:32:37 2020\n",
      "Quit thread......\n",
      "Thread-18: Tue Jul  7 17:32:37 2020\n",
      "Thread-19: Tue Jul  7 17:32:37 2020\n",
      "Thread-20: Tue Jul  7 17:32:37 2020\n",
      "Thread-21: Tue Jul  7 17:32:37 2020\n",
      "Thread-22: Tue Jul  7 17:32:37 2020\n",
      "Thread-24: Tue Jul  7 17:32:37 2020Thread-25: Tue Jul  7 17:32:37 2020\n",
      "\n",
      "Thread-23: Tue Jul  7 17:32:37 2020\n",
      "Thread-18: Tue Jul  7 17:32:42 2020Thread-19: Tue Jul  7 17:32:42 2020\n",
      "\n",
      "Quit thread......\n",
      "Thread-20: Tue Jul  7 17:32:42 2020\n",
      "Thread-21: Tue Jul  7 17:32:42 2020\n",
      "Thread-22: Tue Jul  7 17:32:42 2020\n",
      "Thread-25: Tue Jul  7 17:32:42 2020Thread-23: Tue Jul  7 17:32:42 2020\n",
      "\n",
      "Thread-24: Tue Jul  7 17:32:42 2020\n",
      "Thread-19: Tue Jul  7 17:32:47 2020\n",
      "Quit thread......\n",
      "Thread-20: Tue Jul  7 17:32:47 2020\n",
      "Thread-21: Tue Jul  7 17:32:47 2020\n",
      "Thread-22: Tue Jul  7 17:32:47 2020\n",
      "Thread-23: Tue Jul  7 17:32:47 2020Thread-24: Tue Jul  7 17:32:47 2020Thread-25: Tue Jul  7 17:32:47 2020\n",
      "\n",
      "\n",
      "Thread-20: Tue Jul  7 17:32:52 2020\n",
      "Quit thread......\n",
      "Thread-21: Tue Jul  7 17:32:52 2020\n",
      "Thread-22: Tue Jul  7 17:32:52 2020\n",
      "Thread-24: Tue Jul  7 17:32:52 2020Thread-23: Tue Jul  7 17:32:52 2020\n",
      "\n",
      "Thread-25: Tue Jul  7 17:32:52 2020\n",
      "Thread-21: Tue Jul  7 17:32:57 2020\n",
      "Quit thread......\n",
      "Thread-22: Tue Jul  7 17:32:57 2020\n",
      "Thread-23: Tue Jul  7 17:32:57 2020Thread-25: Tue Jul  7 17:32:57 2020Thread-24: Tue Jul  7 17:32:57 2020\n",
      "\n",
      "\n",
      "Thread-22: Tue Jul  7 17:33:02 2020\n",
      "Quit thread......\n",
      "Thread-25: Tue Jul  7 17:33:02 2020Thread-23: Tue Jul  7 17:33:02 2020\n",
      "\n",
      "Thread-24: Tue Jul  7 17:33:02 2020\n",
      "Thread-25: Tue Jul  7 17:33:07 2020Thread-23: Tue Jul  7 17:33:07 2020\n",
      "\n",
      "Quit thread......\n",
      "Thread-24: Tue Jul  7 17:33:07 2020\n",
      "Thread-24: Tue Jul  7 17:33:12 2020Thread-25: Tue Jul  7 17:33:12 2020\n",
      "\n",
      "Quit thread......\n",
      "Thread-25: Tue Jul  7 17:33:17 2020\n",
      "Quit thread......\n"
     ]
    }
   ],
   "source": [
    "#1.threading类\n",
    "import threading\n",
    "import time\n",
    "flag = 0\n",
    "class MyThread(threading.Thread):\n",
    "    \"\"\"自定义线程，继承父类\"\"\"\n",
    "    def __init__(self,threadid,threadname,counter):\n",
    "        threading.Thread.__init__(self)\n",
    "        \"\"\"定义构造函数，包括ID号、线程名称以及计数器,继承Thread类的构造函数\"\"\"\n",
    "        self.threadid = threadid\n",
    "        self.counter = counter\n",
    "        self.threadname  = threadname\n",
    "    def run(self):\n",
    "        \"\"\"关键：重写run()方法\"\"\"\n",
    "        print(\"Thread start......\")\n",
    "        print(self.threadname)\n",
    "        printValue(self.name,5,self.counter)\n",
    "        print(\"Quit thread......\")\n",
    "\n",
    "def printValue(threadname,delay,counter):\n",
    "    while counter >=0:\n",
    "        if flag:\n",
    "            threadname.exit()\n",
    "        time.sleep(delay)\n",
    "        print (\"%s: %s\" % (threadname, time.ctime(time.time())))\n",
    "        counter -= 1\n",
    "if __name__ =='__main__':\n",
    "    a = []\n",
    "    for i in range(10):\n",
    "        a.append(MyThread(i,('Thread-'+str(i)),i))\n",
    "    for j in range(10):\n",
    "        a[j].start()\n",
    "    for k in range(9,-1,-1):\n",
    "        a[k].join()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 上面使用了threading模块，同时自定义并继承了threading.Thread类\n",
    "\n",
    "线程的生命周期 ![](thread_state.jpg)\n",
    "\n",
    "同时开了10个线程，实现对数据的获取技术。下面的作业要求：\n",
    "\n",
    "# 作业1：1.\t请完成一个多线程的程序\n",
    "\n",
    "实现五个线程同时向一个包含50个元素的列表中存储随机产生的1-6的整数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ThreadA 写入了数据 6\n",
      "ThreadA 写入了数据 ThreadB 写入了数据 6\n",
      "ThreadB 写入了数据 1\n",
      "ThreadB 写入了数据 6\n",
      "ThreadB 写入了数据 65\n",
      "ThreadB 写入了数据 3\n",
      "ThreadB 写入了数据 6\n",
      "ThreadB 写入了数据 3\n",
      "ThreadB 写入了数据 1\n",
      "ThreadB 写入了数据 2\n",
      "ThreadA 写入了数据 2\n",
      "ThreadA 写入了数据 5\n",
      "ThreadA 写入了数据 6\n",
      "ThreadA 写入了数据 6\n",
      "ThreadA 写入了数据 \n",
      "ThreadB 写入了数据 4\n",
      "ThreadB 写入了数据 3\n",
      "ThreadB 1\n",
      "ThreadA ThreadC 写入了数据 2\n",
      "ThreadA 写入了数据 6\n",
      "ThreadA 写入了数据 ThreadD 写入了数据 5\n",
      "ThreadD 写入了数据 5\n",
      "ThreadD 写入了数据 4\n",
      "ThreadD 写入了数据 4\n",
      "ThreadD 写入了数据 3\n",
      "ThreadD 写入了数据 3\n",
      "ThreadD 写入了数据 3\n",
      "ThreadD 写入了数据 6\n",
      "ThreadD 写入了数据 4\n",
      "ThreadD 写入了数据 6\n",
      "ThreadD 写入了数据 1\n",
      "ThreadD 写入了数据 2\n",
      "ThreadD 写入了数据 4\n",
      "ThreadD 写入了数据 4\n",
      "ThreadD 写入了数据 1\n",
      "ThreadD 写入了数据 4\n",
      "ThreadD 写入了数据 5\n",
      "ThreadD 写入了数据 4\n",
      "ThreadD 写入了数据 写入了数据写入了数据 4\n",
      "ThreadB 写入了数据 2\n",
      "ThreadB 写入了数据 2\n",
      "ThreadB 写入了数据 2\n",
      "ThreadB 写入了数据 6\n",
      "ThreadB 写入了数据 3\n",
      "ThreadB 写入了数据 3\n",
      "ThreadB 写入了数据 4\n",
      "ThreadB 写入了数据 2\n",
      "2\n",
      " 250\n",
      "\n",
      "4[6, 5, 6, 1, 6, 6, 3, 6, 3, 1, 2, 2, 5, 6, 6, 1, 4, 3, 4, 2, 4, 6, 2, 5, 5, 4, 4, 3, 3, 3, 6, 4, 6, 1, 2, 4, 4, 1, 4, 5, 4, 2, 2, 2, 2, 6, 3, 3, 4, 2]\n",
      "\n"
     ]
    }
   ],
   "source": [
    "import threading\n",
    "import random\n",
    "a = []\n",
    "class MyTh(threading.Thread):\n",
    "    \"\"\"自定义线程，继承父类的Thread\"\"\"\n",
    "    def __init__(self,name):\n",
    "        threading.Thread.__init__(self)\n",
    "        self.name = name\n",
    "    def run(self):\n",
    "        while  len(a)<50:\n",
    "            r = random.randint(1,6)\n",
    "            a.append(r)\n",
    "            print(self.name,\"写入了数据\",r)\n",
    "if __name__=='__main__':\n",
    "    thread1 = MyTh('ThreadA')\n",
    "    thread2 = MyTh('ThreadB')\n",
    "    thread3 = MyTh('ThreadC')\n",
    "    thread4 = MyTh('ThreadD')\n",
    "    thread5 = MyTh('ThreadE')\n",
    "    thread1.start()\n",
    "    thread2.start()\n",
    "    thread3.start()\n",
    "    thread4.start()\n",
    "    thread5.start()\n",
    "    thread1.join()\n",
    "    thread2.join()\n",
    "    thread3.join()\n",
    "    thread4.join()\n",
    "    thread5.join()  #把主线程让出，避免统计出错\n",
    "    print(len(a))\n",
    "    print(a)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
